<?php

require_once __DIR__ . '/../../vendor/autoload.php';

use PhpAmqpLib\Connection\AMQPStreamConnection;
use PhpAmqpLib\Exchange\AMQPExchangeType;

ignore_user_abort(); //后台运行
set_time_limit(0); //取消脚本运行时间的超时上限

$queueName = 'msgs'; //队列名称
$consumerTag = 'consumer1'; //消费者标识符
$exchangeName = 'kd_sms_send_ex'; //交换机名
$routingKey = 'sms_send'; //路由关键字(也可以省略)

//建立生产者与mq之间的连接, rabbitMQ安装好后默认的端口是5672，防火墙记得打开，默认用户名和密码都是guest
//$connection = new AMQPStreamConnection('localhost', 5672, 'guest', 'guest');
$connection = new AMQPStreamConnection(
    '120.25.227.106',
    5672,
    'guest',  //user
    'guest',  //password
    '/'  //vhost
);

$connection = new AMQPStreamConnection(
    '127.0.0.1',
    5672,
    'guest',
    'guest',
    '/',
    false,
    'AMQPLAIN',
    null,
    'en_US',
    3.0,
    3.0,
    null,
    false,
    30   //心跳时间 默认0[可能假死不消费]
);

//在已连接基础上建立生产者与mq之间的通道
$channel = $connection->channel();

//声明初始化交换机
//参数：交换机名，路由类型，是否检测同名队列，是否开启队列持久化，通道关闭后是否删除队列
$channel->exchange_declare($exchangeName, 'direct', false, true, false);

//声明初始化队列
//参数：队列名，是否检测同名队列，是否开启队列持久化，是否能被其他队列访问，通道关闭后是否删除队列
$channel->queue_declare($queueName, false, true, false, false);

//将队列与某个交换机进行绑定，并使用路由关键字
//参数：队列名，交换机名，路由键名
$channel->queue_bind($queueName, $exchangeName, $routingKey);

echo ' [*] Waiting for messages. To exit press CTRL+C' . PHP_EOL;

//定义回调方法，内部是需要执行的语句
$callback = function ($msg) {
    echo " Received message：", $msg->body, PHP_EOL;

    //模拟耗时执行
    sleep(1);

    //消息确认，手动ack应答
    $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);

    /*$msg->ack();
    //判断获取到quit后退出
    if (trim($msg->body) == 'quit') {
        $msg->getChannel()->basic_cancel($msg->getConsumerTag());
    }*/
};

//处理和确认完消息后再消费新的消息
$channel->basic_qos(null, 1, null);

//指派相应的队列去执行回调方法，第4个参数值为false表示启用消息确认
//参数：队列名，消费者标识符，不接收此使用者发布的消息，使用者是否使用自动确认模式，请求独占使用者访问，不等待，消息回调函数
//1:queue 要取得消息的队列名
//2:consumer_tag 消费者标签
//3:no_local false这个功能属于AMQP的标准,但是rabbitMQ并没有做实现.参考
//4:no_ack  false收到消息后,是否不需要回复确认即被认为被消费
//5:exclusive false排他消费者,即这个队列只能由一个消费者消费.适用于任务不允许进行并发处理的情况下.比如系统对接
//6:nowait  false不返回执行结果,但是如果排他开启的话,则必须需要等待结果的,如果两个一起开就会报错
//7:callback  null回调函数
//8:ticket  null
//9:arguments null
$channel->basic_consume($queueName, $consumerTag, false, false, false, false, $callback);


//退出方法
function shutdown($channel, $connection)
{
    $channel->close();
    $connection->close();
}

//注册退出函数
register_shutdown_function('shutdown', $channel, $connection);

//监听通道消息
while (count($channel->callbacks)) {
    $channel->wait();
}

//$channel->close();
//$connection->close();